package com.ruoyi.framework.interceptor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.ExceptionEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.framework.web.service.ApiTokenService;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.service.IUserService;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * 登录拦截器  拦截小程序接口
 */
@Component
public class LoginApiInterceptor implements HandlerInterceptor {

    @Resource
    private ApiTokenService apiTokenService;

    @Resource
    private IUserService userService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断是否存在令牌信息，如果存在，则允许登录
        //token_access 这就是前端放在请求头中的jwtToken
        String accessToken = request.getHeader(Constants.API_TOKEN);
        if (ObjectUtil.isEmpty(accessToken)) {
            //这里抛给前端的为一个自定义异常枚举，可自己定义
            throw new ServiceException(ExceptionEnum.USER_NOT_LOGIN);
        }
        try {
            Object cacheObject = RedisUtils.getCacheObject(Constants.APP_ONLINE_TOKEN_KEY + accessToken);
            User apiUser = BeanUtil.toBean(cacheObject, User.class);
            if (ObjectUtil.isNotEmpty(apiUser)) {
                User user = userService.getById(apiUser.getId(), false);
                if (ObjectUtil.isNull(user)) {
                    throw new ServiceException(ExceptionEnum.USER_NOT_EXISTS);
                }
                //如果用户被禁用，则不能登录
                if (user.getStatus() == 1) {
                    throw new ServiceException(ExceptionEnum.USER_DISABLED);
                }
                //这个可要可不要，通过这里自己在请求中加参数，可以让前端少传几个已经在token中自定义好的值
                UserContext.setUser(user);
            } else {
                throw new ServiceException(ExceptionEnum.TOKEN_EXPIRED);
            }
        } catch (ExpiredJwtException e) {
            throw new ServiceException(ExceptionEnum.TOKEN_EXPIRED);
        } catch (MalformedJwtException e) {
            throw new ServiceException(ExceptionEnum.TOKEN_ERROR);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
        modelAndView) {
        UserContext.close();
    }
}
